package com.orange.shiro.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.orange.shiro.realm.MyRealm;
import net.sf.ehcache.CacheManager;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authc.pam.AllSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.io.ResourceUtils;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

@Configuration
public class ShiroConfig {

    @Autowired
    private MyRealm myRealm;

    //配置SecurityManager
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager() {
        //1.创建defaultWebSecurityManager 对象
        //2.创建加密对象，设置相关属性
        //3.将加密对象存储到myRealm中
        //4.将myRealm对象存储到defaultWebSecurityManager 对象
        //5.返回

        //1.创建defaultWebSecurityManager 对象
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();

        //创建认证对象，并设置认证策略
        ModularRealmAuthenticator modularRealmAuthenticator = new ModularRealmAuthenticator();
        modularRealmAuthenticator.setAuthenticationStrategy(new AllSuccessfulStrategy());
        defaultWebSecurityManager.setAuthenticator(modularRealmAuthenticator);

        //2.创建加密对象，设置相关属性
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        //2.1 采用MD5加密
        matcher.setHashAlgorithmName("md5");
        //2.2 采用迭代加密的次数
        matcher.setHashIterations(5);
        //3.将加密对象存储到myRealm中
        myRealm.setCredentialsMatcher(matcher);

        //封装myRealm集合
        ArrayList<Realm> list = new ArrayList<>();
        list.add(myRealm);
        //list.add(myRealm2);

        //4.将myRealm对象存储到defaultWebSecurityManager 对象
        defaultWebSecurityManager.setRealms(list);
        //4.1设置RememberMe
        defaultWebSecurityManager.setRememberMeManager(rememberMeManager());
        //4.2设置缓存管理器
        defaultWebSecurityManager.setCacheManager(getEhcacheManager());

        //5.返回
        return defaultWebSecurityManager;
    }

    //缓存管理器获取
    private EhCacheManager getEhcacheManager() {
        EhCacheManager ehCacheManager = new EhCacheManager();
        //获取编译目录下的资源的流对象
        InputStream is = null;
        try {
            is = ResourceUtils.getInputStreamForPath("classpath:ehcache/ehcache-shiro.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取 EhCache的缓存管理对象 net.sf.ehcache.CacheManager
        CacheManager cacheManager = new CacheManager(is);
        ehCacheManager.setCacheManager(cacheManager);
        return ehCacheManager;
    }

    //cookie属性设置
    public SimpleCookie rememberMeCookie() {
        SimpleCookie cookie = new SimpleCookie("rememberMe");
        //设置跨域
        //cookie.setDomain(domain);
        cookie.setPath("/");
        cookie.setHttpOnly(true);
        cookie.setMaxAge(30 * 24 * 60 * 60);
        return cookie;
    }

    //创建Shiro的cookie管理对象
    public CookieRememberMeManager rememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        //AES的秘钥一定要是16位秘钥
        //Caused by: java.security.InvalidKeyException: Invalid AES key length: 10 bytes
        //cookieRememberMeManager.setCipherKey("1234567890".getBytes());
        cookieRememberMeManager.setCipherKey("1234567890123456".getBytes());
        return cookieRememberMeManager;
    }

    //配置 Shiro 内置过滤拦截范围
    @Bean
    public DefaultShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();
        //设置不可认证可以访问的资源
        definition.addPathDefinition("/myController/userLogin", "anon");
        definition.addPathDefinition("/myController/login", "anon");

        //配置登出过滤器
        definition.addPathDefinition("/logout", "logout");
        //设置需要进行登录认证的拦截范围
        definition.addPathDefinition("/**", "authc");

        //添加存在的用户过滤器rememberMe
        definition.addPathDefinition("/**", "user");

        //返回
        return definition;
    }

    //用于解析 thymeleaf中的 shiro:相关属性
    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }

}
